package com.wangl.spring.utils;

import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtilBase;
import com.intellij.psi.util.PsiUtil;
import com.wangl.spring.suggestion.SuggestionNodeTree;
import com.wangl.spring.suggestion.SuggestionNodeType;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName SpringBootPropertiesResolver
 * @Description TODO
 * @Author wangl
 * @Date 2023/3/24 15:58
 */
public class SpringBootPropertiesResolver {

    public static boolean isAnnotatedConfigurationProperties(PsiClass psiClass) {
        PsiAnnotation configurationPropertiesAnnotation = psiClass.getAnnotation(Annotations.CONFIGURATION_PROPERTIES);
        return configurationPropertiesAnnotation != null;
    }

    public static boolean isAnnotatedConfigurationProperties(PsiMethod method){
        return method.getAnnotation(Annotations.BEAN) != null &&
                method.getAnnotation(Annotations.CONFIGURATION_PROPERTIES) != null &&
                method.hasModifierProperty(PsiModifier.PUBLIC) &&
                !method.hasModifierProperty(PsiModifier.STATIC) &&
                !method.hasParameters() &&
                !PsiType.VOID.equals(method.getReturnType());
    }

    public static boolean isConfiguration(PsiClass psiClass){
        PsiAnnotation configuration = psiClass.getAnnotation(Annotations.CONFIGURATION);
        return configuration != null;
    }

    public static boolean isAnnotationConditionalOnProperty(PsiClass psiClass){
        PsiAnnotation conditionalOnProperty = psiClass.getAnnotation(Annotations.CONDITIONAL_ON_PROPERTY);
        return conditionalOnProperty != null;
    }

    public static boolean isComponent(PsiClass psiClass){
        PsiAnnotation component = psiClass.getAnnotation(Annotations.COMPONENT);
        PsiAnnotation repository = psiClass.getAnnotation(Annotations.REPOSITORY);
        PsiAnnotation service = psiClass.getAnnotation(Annotations.SERVICE);
        PsiAnnotation controller = psiClass.getAnnotation(Annotations.CONTROLLER);
        return component != null || repository != null || service != null || controller != null || isConfiguration(psiClass);
    }

    public static boolean isNonGenericType(PsiClassType classType) {
        PsiType[] parameters = classType.getParameters();
        return parameters.length == 0 && !classType.isRaw();
    }

    public static boolean isApplicationPropertiesKey(PsiType type){
        SuggestionNodeType suggestionNodeType = PsiCustomUtil.getSuggestionNodeType(type);
        if (suggestionNodeType == SuggestionNodeType.UNKNOWN_CLASS){
            return false;
        }
        if (suggestionNodeType.representsPrimitiveOrString()){
            return true;
        }
        if (suggestionNodeType == SuggestionNodeType.ITERABLE || suggestionNodeType == SuggestionNodeType.MAP){
            Map<PsiTypeParameter, PsiType> typeParameters = PsiCustomUtil.getTypeParameters(type);
            if (typeParameters == null){
                return false;
            }
            return typeParameters.values().stream()
                    .allMatch(t -> PsiCustomUtil.getSuggestionNodeType(t).representsPrimitiveOrString());
        }
        return false;
    }
}
